package com.gobang.websocket;

import com.gobang.websocket.dispatcher.WebSocketMessageDispatcher;
import com.gobang.websocket.session.WebSocketSessionManager;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

/**
 * 核心 WebSocket 处理器
 *
 * 负责连接建立 / 关闭事件与文本消息转发到调度器。
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class GameWebSocketHandler extends TextWebSocketHandler {

    private final WebSocketSessionManager webSocketSessionManager;
    private final WebSocketMessageDispatcher webSocketMessageDispatcher;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        Long userId = extractUserId(session);
        if (userId == null) {
            log.warn("WebSocket 连接建立失败，缺少 userId 属性, sessionId={}", session.getId());
            session.close(CloseStatus.NOT_ACCEPTABLE.withReason("Unauthorized"));
            return;
        }

        webSocketSessionManager.registerSession(userId, session);
        log.info("WebSocket 连接建立成功: userId={}, sessionId={}", userId, session.getId());
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        webSocketMessageDispatcher.dispatch(session, message.getPayload());
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        webSocketSessionManager.removeSession(session);
        log.info("WebSocket 连接关闭: sessionId={}, status={}", session.getId(), status);
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        log.error("WebSocket 传输异常: sessionId={}, error={}",
                session != null ? session.getId() : "null",
                exception.getMessage(), exception);
        if (session != null && session.isOpen()) {
            session.close(CloseStatus.SERVER_ERROR);
        }
        if (session != null) {
            webSocketSessionManager.removeSession(session);
        }
    }

    private Long extractUserId(WebSocketSession session) {
        Object attr = session.getAttributes().get("userId");
        if (attr instanceof Long l) {
            return l;
        }
        if (attr instanceof Integer i) {
            return i.longValue();
        }
        if (attr != null) {
            try {
                return Long.valueOf(attr.toString());
            } catch (NumberFormatException e) {
                log.warn("无法从 WebSocketSession 属性解析 userId: {}", attr);
            }
        }
        return null;
    }
}
